﻿'// ========================================================================= '
'// ------------------------------------------------------------------------- '
'//!				\file		CD_Ins.vb
'			        \date		june 2010
'			        \author		TNick
'
'			        \brief		Dialog for symbols insertion
'
'
'   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'   This file is considered universal knowledge. No restrictions
'   are imposed; use as you see fit.
'   Please read ReadMe.txt and Licence.txt in root folder
'   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'
'   
'
'// ------------------------------------------------------------------------- '
'// ========================================================================= '
'//
'//
'//
'//
'//  IMPORTS     ------------------------------------------------------------ '
#Region "Imports"

Imports System.Windows.Forms
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Geometry

#End Region
'//  IMPORTS     ============================================================ '
'//
'//
'//
'//
'//  DEFINITIONS    --------------------------------------------------------- '


Public Structure ISPRP
    '// boolean value that tells the source of th definition
    Dim bFromDB As Boolean
    '// if the source of the block is a document, this is a reference to it
    Dim acDocSrc As Document
    '// if the source is in database, this is the one
    Dim acSrcDb As Database
    '// the ID of the block in source
    Dim acOId As ObjectId
    '// the name of the block
    Dim sName As String
    '// the scale of the block
    Dim dScl As Double
    '// the rotation of the block
    Dim dRot As Double
    '// the distance between two consecutive blocks
    Dim dSpan As Double

End Structure

'//  DEFINITIONS    ========================================================= '
'//
'//
'//
'//
'//  DATA    ---------------------------------------------------------------- '


'//  DATA    ================================================================ '
'//
'//
'//
'//
'//  CLASS    --------------------------------------------------------------- '

Public Class CD_Ins
    '// defines the colors used in list
    Public colCrt As new System.Drawing.Color()
    Public colDbf As new System.Drawing.Color()
    Public colOther As new System.Drawing.Color()

#Region "Internal work"
    '// --------------------------------------------------------------------- '
    '// gets the current properties
    Private Function GetPrp(ByRef locStg As ISPRP) As Boolean
        Dim bRet As Boolean = False
        Try
            locStg.acDocSrc = Nothing
            locStg.acSrcDb = Nothing
            If (Me.LV_Syms.SelectedItems.Count <> 1) Then
                MsgBox(locStg.sName & vbNewLine & _
                     CMain._T(TX.NOSELLI), _
                    MsgBoxStyle.Critical, _
                    CMain._T(TX.ERR))
                Exit Try
            End If
            If CMain.GetTxDbl(Me.TX_Rot, locStg.dRot) = False Then Exit Try
            If CMain.GetTxDbl(Me.TX_Scale, locStg.dScl) = False Then Exit Try
            If CMain.GetTxDbl(Me.TX_Span, locStg.dSpan) = False Then Exit Try


            locStg.sName = Me.LV_Syms.SelectedItems(0).Text
            If Me.LV_Syms.SelectedItems(0).SubItems(1).Text = CMain._T(TX.DBF) Then
                '// this block is located in database
                locStg.bFromDB = True

                '// search external database
                locStg.acSrcDb = _
                    New Database(False, True)
                Try
                    ' Read the DWG into a side database
                    locStg.acSrcDb.ReadDwgFile(CM_Symbols.Stgs.sDBPath, _
                                        System.IO.FileShare.Read, True, "")

                    Using myT As Transaction = locStg.acSrcDb. _
                        TransactionManager.StartTransaction()

                        ' Open the block table
                        Dim bt As BlockTable = DirectCast( _
                            myT.GetObject(locStg.acSrcDb.BlockTableId, _
                                         OpenMode.ForRead, False),  _
                                        BlockTable)

                        If (bt.Has(locStg.sName)) Then
                            '// there it is
                            locStg.acOId = bt(locStg.sName)
                            bRet = True
                        Else
                            '// database no longer has this block
                            MsgBox(locStg.sName & vbNewLine & _
                                 CMain._T(TX.SYM_EDEL), _
                                MsgBoxStyle.Critical, _
                                CMain._T(TX.ERR))
                        End If

                    End Using
                Catch ex As System.Exception
                    CMain.DebugException(ex)
                    If Not locStg.acSrcDb Is Nothing Then
                        locStg.acSrcDb.Dispose()
                        locStg.acSrcDb = Nothing
                    End If
                End Try

            Else
                '// located in on of the drawings
                locStg.bFromDB = False

                For Each acDoc As Document In Autodesk.AutoCAD.ApplicationServices. _
                            Application.DocumentManager
                    If acDoc.Name = Me.LV_Syms.SelectedItems(0).SubItems(1).Text Then
                        locStg.acDocSrc = acDoc
                        '// check to see if it's still there
                        Using acDocLk As DocumentLock = acDoc.LockDocument()
                            Using myT As Transaction = acDoc.Database. _
                                TransactionManager.StartTransaction()

                                ' Open the block table
                                Dim bt As BlockTable = DirectCast( _
                                    myT.GetObject(acDoc.Database.BlockTableId, _
                                                 OpenMode.ForRead, False),  _
                                                BlockTable)
                                If (bt.Has(Me.LV_Syms.SelectedItems(0).Text)) Then
                                    '// there it is
                                    bRet = True
                                    locStg.acOId = _
                                        bt(Me.LV_Syms.SelectedItems(0).Text)
                                Else
                                    '// has been removed
                                    MsgBox(locStg.sName & vbNewLine & _
                                         CMain._T(TX.SYM_EDEL), _
                                        MsgBoxStyle.Critical, _
                                        CMain._T(TX.ERR))
                                End If

                            End Using
                        End Using
                    End If

                Next
                '// if execution reaches this point the drawing must have been closed
            End If
        Catch ex As System.Exception
            CMain.DebugException(ex)
        Finally
        End Try
        Return bRet
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// release the current properties
    Private Sub DisposePrp(ByRef locStg As ISPRP)
        locStg.acDocSrc = Nothing
        If Not (locStg.acSrcDb = Nothing) Then
            locStg.acSrcDb.Dispose()
            locStg.acSrcDb = Nothing
        End If
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub ScanForBlocks()
        Dim acDocC As Document = Autodesk.AutoCAD.ApplicationServices. _
            Application.DocumentManager.MdiActiveDocument
        If acDocC Is Nothing Then
            Me.Close()
            Return
        End If

        '// search external database
        Dim acSrcDb As Database = _
            New Database(False, True)
        Try
            ' Read the DWG into a side database
            acSrcDb.ReadDwgFile(CM_Symbols.Stgs.sDBPath, _
                                System.IO.FileShare.Read, True, "")

            Using myT As Transaction = acSrcDb. _
                TransactionManager.StartTransaction()

                ' Open the block table
                Dim bt As BlockTable = DirectCast( _
                    myT.GetObject(acSrcDb.BlockTableId, _
                                 OpenMode.ForRead, False),  _
                                BlockTable)

                ' Check each block in the block table
                For Each btrId As ObjectId In bt
                    Dim btr As BlockTableRecord = DirectCast( _
                    myT.GetObject(btrId, OpenMode.ForRead, False),  _
                    BlockTableRecord)
                    ' Only add named & non-layout blocks to the copy list
                    If Not btr.IsAnonymous AndAlso Not btr.IsLayout Then

                        Dim li As System.Windows.Forms.ListViewItem
                        li = Me.LV_Syms.Items.Add(btr.Name)
                        li.SubItems.Add(CMain._T(TX.DBF))
                        li.ForeColor = colDbf

                    End If
                    btr.Dispose()
                Next
            End Using

        Catch ex As System.Exception
            CMain.DebugException(ex)
        Finally
            If Not acSrcDb Is Nothing Then
                acSrcDb.Dispose()
                acSrcDb = Nothing
            End If
        End Try



        For Each acDoc as Document In Autodesk.AutoCAD.ApplicationServices. _
                    Application.DocumentManager
            '// check to see if it's still there
            Using acDocLk As DocumentLock = acDoc.LockDocument()
                Using myT As Transaction = acDoc.Database. _
                    TransactionManager.StartTransaction()

                    acSrcDb = acDoc.Database
                    Try

                        Using myT2 As Transaction = acSrcDb. _
                            TransactionManager.StartTransaction()
                            ' Open the block table
                            Dim bt As BlockTable = DirectCast( _
                                myT2.GetObject(acSrcDb.BlockTableId, _
                                             OpenMode.ForRead, False),  _
                                            BlockTable)

                            ' Check each block in the block table
                            For Each btrId As ObjectId In bt
                                Dim btr As BlockTableRecord = DirectCast( _
                                myT2.GetObject(btrId, OpenMode.ForRead, False),  _
                                BlockTableRecord)
                                ' Only add named & non-layout blocks to the copy list
                                If Not btr.IsAnonymous AndAlso Not btr.IsLayout Then

                                    Dim li As System.Windows.Forms.ListViewItem
                                    li = Me.LV_Syms.Items.Add(btr.Name)
                                    li.SubItems.Add(acDoc.Name)
                                    If (acDocC = acDoc) then
                                        li.ForeColor = colCrt
                                    Else
                                        li.ForeColor = colOther
                                    End If
                                End If
                            Next
                        End Using

                    Catch ex As System.Exception
                        CMain.DebugException(ex)
                    Finally
                        If Not acSrcDb Is Nothing Then
                            acSrcDb.Dispose()
                        End If
                    End Try


                End Using
            End Using

        Next


    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// Actually place blocks on a line
    Private Sub DW_PlaceOnLine( _
        ByRef lcSet As ISPRP, _
        ByRef acDoc As Document, _
        ByRef acT As Transaction, _
        ByRef acId As ObjectId, _
        ByRef dN1 As Double, ByRef dE1 As Double, _
        ByVal dAng As Double, _
        ByVal dDst As Double)


        ' Get Model space (is just a block)
        Dim acBlkSpace As BlockTableRecord = DirectCast( _
            acT.GetObject(acDoc.Database.CurrentSpaceId, _
                OpenMode.ForWrite),  _
            BlockTableRecord)

        Dim iCnt As Integer
        Dim dTrueSpan As Double
        Dim dCrtN As Double
        Dim dCrtE As Double
        Dim dAdvN As Double
        Dim dAdvE As Double
        Dim bSingl As Boolean = False

        If (lcSet.dSpan >= dDst) Then
            iCnt = 1
            dTrueSpan = dDst / 2
            bSingl = True
        Else
            iCnt = CInt(dDst / lcSet.dSpan)
            dTrueSpan = dDst / (iCnt + 1)
        End If
        dAdvN = Math.Sin(dAng) * dTrueSpan
        dAdvE = Math.Cos(dAng) * dTrueSpan


        dCrtN = dN1 + dAdvN
        dCrtE = dE1 + dAdvE
        For i As Integer = 0 To iCnt - 1

            ' Create a block reference
            Dim br As BlockReference = _
                New BlockReference( _
                    New Point3d(dCrtE, dCrtN, 0), _
                    acId)
            br.SetDatabaseDefaults()
            br.ScaleFactors = New Autodesk.AutoCAD.Geometry.Scale3d( _
                lcSet.dScl, lcSet.dScl, lcSet.dScl)
            br.Rotation = dAng + lcSet.dRot

            ' Add the block reference to Model space
            acBlkSpace.AppendEntity(br)
            acT.AddNewlyCreatedDBObject(br, True)

            dCrtN = dCrtN + dAdvN
            dCrtE = dCrtE + dAdvE
        Next i

        If bSingl = False

            ' Create a block reference
            Dim br As BlockReference = _
                New BlockReference( _
                    New Point3d(dCrtE, dCrtN, 0), _
                    acId)
            br.SetDatabaseDefaults()
            br.ScaleFactors = New Autodesk.AutoCAD.Geometry.Scale3d( _
                lcSet.dScl, lcSet.dScl, lcSet.dScl)
            br.Rotation = dAng + lcSet.dRot

            ' Add the block reference to Model space
            acBlkSpace.AppendEntity(br)
            acT.AddNewlyCreatedDBObject(br, True)

        End If


    End Sub
    '// ===================================================================== '


    '// --------------------------------------------------------------------- '
    '// do dirty work for insert one by one
    Private Sub DW_InsOne( _
        ByRef lcSet As ISPRP, _
        ByRef acDoc As Document, _
        ByRef acId As ObjectId)

        '// we simply pick points and insert objects
        Dim ppo As PromptPointOptions
        Dim ppr As PromptPointResult
        Dim dN1 As Double, dE1 As Double

        Do
            Using acT As Transaction = acDoc.Database. _
                TransactionManager.StartTransaction()
            Try
                ' Get Model space (is just a block)
                Dim acBlkSpace As BlockTableRecord = DirectCast( _
                    acT.GetObject(acDoc.Database.CurrentSpaceId, _
                        OpenMode.ForWrite),  _
                    BlockTableRecord)
                '// get insertion point
                ppo = New PromptPointOptions(vbLf & CMain._T(TX.PICKPOINT) & ":")
                ppo.UseBasePoint = False
                ppr = acDoc.Editor.GetPoint(ppo)
                If ppr.Status = PromptStatus.OK Then
                    dN1 = ppr.Value.Y
                    dE1 = ppr.Value.X
                Else
                    Return
                End If

                ' Create a block reference
                Dim br As BlockReference = _
                    New BlockReference( _
                        ppr.Value, _
                        acId)
                br.SetDatabaseDefaults()
                br.ScaleFactors = New Autodesk.AutoCAD.Geometry.Scale3d( _
                    lcSet.dScl, lcSet.dScl, lcSet.dScl)
                br.Rotation = lcSet.dRot

                ' Add the block reference to Model space
                acBlkSpace.AppendEntity(br)
                acT.AddNewlyCreatedDBObject(br, True)

                acT.Commit()
                Catch ex As System.Exception
                    acT.Abort()
                    CMain.DebugException(ex)
                End Try
            End Using
        Loop

    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// do dirty work for insert on polyline
    Private Sub DW_InsPly( _
        ByRef lcSet As ISPRP, _
        ByRef acDoc As Document, _
        ByRef acId As ObjectId)

		    Dim peo As PromptEntityOptions = Nothing
            Dim acVp As Viewport = Nothing
            Dim pso As  New PromptSelectionOptions()
    
	        '' Get the PickFirst selection set
	        Dim acSSPrompt As PromptSelectionResult = acDoc.Editor.SelectImplied()
	        '' If the prompt status is OK, objects were selected before
	        '' the command was started
	        If acSSPrompt.Status <> PromptStatus.OK Then
                HaveUserSelect:
                pso.SinglePickInSpace = True
                pso.MessageForAdding = vbLf & CMain._T(TX.SELVP) & ": "
                acSSPrompt = _
                    acDoc.Editor.GetSelection(pso)
	            If acSSPrompt.Status <> PromptStatus.OK Then Exit sub
            End if
	        Dim acSSet As SelectionSet = acSSPrompt.Value
            Dim iPoly As Integer = 0, iOther As Integer = 0

        Using acT As Transaction = acDoc.Database. _
            TransactionManager.StartTransaction()
        Try
            For Each sobj As SelectedObject In acSSet
                ' Get Model space (is just a block)
                Dim acBlkSpace As BlockTableRecord = DirectCast( _
                    acT.GetObject(acDoc.Database.CurrentSpaceId, _
                        OpenMode.ForWrite),  _
                    BlockTableRecord)
                Dim TheObj As DBObject
                TheObj = acT.GetObject(sobj.ObjectId,OpenMode.ForRead)
                If (TypeOf TheObj Is Polyline)
                    Dim acPoly As Polyline = DirectCast(TheObj, Polyline)
                    iPoly = iPoly + 1
                    
                    '// this is a polyline; let's add some symbols
                    Dim acPt2 As Point2d = acPoly.GetPoint2dAt(0)
                    Dim dN1 As Double = acPt2.Y, dE1 As Double = acPt2.X
                    Dim dDn As Double, dDe As Double
                    
                    For i As Integer = 1 to acPoly.NumberOfVertices-1
                        acPt2 = acPoly.GetPoint2dAt(i)
                        dDn = acPt2.Y - dN1
                        dDe = acPt2.X - dE1
                        If ((Math.Abs(dDn) < CMain.MARGIN) AndAlso _
                            (Math.Abs(dDe) < CMain.MARGIN)) Then
                            
                            Continue For
                        End If

                        DW_PlaceOnLine( _
                            lcSet, _
                            acDoc, _
                            acT, _
                            acId, _
                            dN1, dE1, _
                            Math.Atan2(dDn, dDe), _
                            Math.Sqrt(dDn * dDn + dDe * dDe))
                        
                        dN1 = acPt2.Y
                        dE1 = acPt2.X
                    Next
                    If acPoly.Closed = True tHEN
                        '// account for closed polylines
                        acPt2 = acPoly.GetPoint2dAt(0)
                        dDn = acPt2.Y - dN1
                        dDe = acPt2.X - dE1
                        If ((Math.Abs(dDn) > CMain.MARGIN) Or _
                            (Math.Abs(dDe) > CMain.MARGIN)) Then
                            
                            DW_PlaceOnLine( _
                                lcSet, _
                                acDoc, _
                                acT, _
                                acId, _
                                dN1, dE1, _
                                Math.Atan2(dDn, dDe), _
                                Math.Sqrt(dDn * dDn + dDe * dDe))
                        End If
                    End If

                Else
                    iOther = iOther + 1
                End If
            Next
            acT.Commit()
            Catch ex As System.Exception
                acT.Abort()
                CMain.DebugException(ex)
            End Try
        End Using
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// do dirty work for insert on direction
    Private Sub DW_InsDir( _
        ByRef lcSet As ISPRP, _
        ByRef acDoc As Document, _
        ByRef acId As ObjectId)

        Dim ppo As PromptPointOptions
        Dim ppr As PromptPointResult
        Dim dN1 As Double, dE1 As Double

        ppo = New PromptPointOptions(vbLf & CMain._T(TX.FPOINT) & ":")


        ppr = acDoc.Editor.GetPoint(ppo)
        ppo.UseBasePoint = True
        If ppr.Status = PromptStatus.OK Then
            dN1 = ppr.Value.Y
            dE1 = ppr.Value.X
        Else
            Return
        End If

        ppo.Message = vbLf & CMain._T(TX.SPOINT) & ":"
        Do
            ppo.BasePoint = ppr.Value
            ppo.UseBasePoint = True
            Dim dDn As Double
            Dim dDe As Double
            Do
                ppr = acDoc.Editor.GetPoint(ppo)
                If ppr.Status <> PromptStatus.OK Then Return

                dDn = ppr.Value.Y - dN1
                dDe = ppr.Value.X - dE1

                If Math.Abs(dDn) > CMain.MARGIN Then
                    Exit Do
                End If
                If Math.Abs(dDe) > CMain.MARGIN Then
                    Exit Do
                End If
                CMain.AlertUser(TX.ERR_PTCLOSE)
            Loop
            Using acT As Transaction = acDoc.Database. _
                TransactionManager.StartTransaction()
            Try

                DW_PlaceOnLine( _
                    lcSet, _
                    acDoc, _
                    acT, _
                    acId, _
                    dN1, dE1, _
                    Math.Atan2(dDn, dDe), _
                    Math.Sqrt(dDn * dDn + dDe * dDe))

                ppo.Message = vbLf & CMain._T(TX.NEXTPOINT) & ":"
                dN1 = ppr.Value.Y
                dE1 = ppr.Value.X
                acT.Commit()
            Catch ex As System.Exception
                acT.Abort()
                CMain.DebugException(ex)
            End Try
            End Using
        Loop



    End Sub
    '// ===================================================================== '





    '// --------------------------------------------------------------------- '
    '// Base of action
    Private Enum ACTY
        ERR = 0
        REGISTER
        INS_POINT
        INS_DIR
        INS_POLY
    End Enum

    Private Sub ActionBase(ByVal ty As ACTY, ByRef sNewAdded As String)

        sNewAdded = Nothing
        Dim lcStg As ISPRP = Nothing
        Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices. _
            Application.DocumentManager.MdiActiveDocument
        If acDoc Is Nothing Then
            Me.Close()
            Return
        End If

        If GetPrp(lcStg) = True Then
            If (ty = ACTY.REGISTER) Then
            If (lcStg.bFromDB = False) Then
                If (lcStg.acDocSrc = acDoc) Then
                    MsgBox(lcStg.sName & vbNewLine & _
                         CMain._T(TX.SYM_EPRES), _
                        MsgBoxStyle.Critical, _
                        CMain._T(TX.ERR))
                    DisposePrp(lcStg)
                    Return
                End If
            End If
            End If

            Dim acIdmap As New IdMapping()
            Dim acOidCol As New ObjectIdCollection()
            acOidCol.Add(lcStg.acOId)
            Dim oId As ObjectId


            Using acDocLk As DocumentLock = acDoc.LockDocument()
                Using myT As Transaction = acDoc.Database. _
                    TransactionManager.StartTransaction()

                    Try

                        ' Open the block table
                        Dim bt As BlockTable = DirectCast( _
                            myT.GetObject(acDoc.Database.BlockTableId, _
                                         OpenMode.ForRead, False),  _
                                        BlockTable)

                        If bt.Has(lcStg.sName) Then
                            If (lcStg.bFromDB = False) Then
                                If (lcStg.acDocSrc = acDoc) Then
                                    oId = lcStg.acOId
                                    GoTo Have_Definition
                                End If
                            End If
                            If ( _
                                MsgBox(lcStg.sName & vbNewLine & _
                                 CMain._T(TX.SYM_HAS), _
                                MsgBoxStyle.YesNo, _
                                CMain._T(TX.ASKQ)) = MsgBoxResult.No) Then

                                GoTo CopyFromDrawing
                            End If
                        Else
                            sNewAdded = lcStg.sName 
                        End If
                        '// we need to copy the definition
                        If (lcStg.bFromDB = True) Then

                            lcStg.acSrcDb.WblockCloneObjects( _
                                acOidCol, _
                                acDoc.Database.BlockTableId, _
                                acIdmap, _
                                DuplicateRecordCloning.Replace, _
                                False)
                            oId = acIdmap(lcStg.acOId).Value
                        ElseIf acDoc <> lcStg.acDocSrc Then
                CopyFromDrawing:
                            lcStg.acDocSrc.Database.WblockCloneObjects( _
                                acOidCol, _
                                acDoc.Database.BlockTableId, _
                                acIdmap, _
                                DuplicateRecordCloning.Replace, _
                                False)
                            oId = acIdmap(lcStg.acOId).Value
                        Else
                            oId = lcStg.acOId
                        End If
Have_Definition:

                        myT.Commit()
                        Catch ex As System.Exception
                            myT.Abort()
                            CMain.DebugException(ex)
                            ty = ACTY.ERR
                        End Try
                End Using

                Select Case ty
                    Case ACTY.REGISTER
                        MsgBox(lcStg.sName & vbNewLine & _
                             CMain._T(TX.SYM_DEFIMP), _
                            MsgBoxStyle.Information, _
                            CMain._T(TX.OK))
                    Case ACTY.INS_POINT
                        DW_InsOne( _
                            lcStg, _
                            acDoc, _
                            oId)
                    Case ACTY.INS_DIR
                        DW_InsDir( _
                            lcStg, _
                            acDoc, _
                            oId)
                    Case ACTY.INS_POLY
                        DW_InsPly( _
                            lcStg, _
                            acDoc, _
                            oId)
                End Select


            End Using

            If Not acIdmap Is Nothing Then
                acIdmap.Dispose()
            End If
            If Not acOidCol Is Nothing Then
                acOidCol.Dispose()
            End If

        End If
        DisposePrp(lcStg)

    End Sub
    '// ===================================================================== '
#End Region


#Region "Other events"
    ' The column currently used for sorting.
    Private m_SortingColumn As ColumnHeader

    '// --------------------------------------------------------------------- '
    Private Sub LV_Syms_ColumnClick( _
        ByVal sender As System.Object,  _
        ByVal e As System.Windows.Forms.ColumnClickEventArgs) _
        Handles LV_Syms.ColumnClick
        '// code copied from
'// http://www.vb-helper.com/howto_net_listview_sort_clicked_column.html

        ' Get the new sorting column.
        Dim new_sorting_column As ColumnHeader = _
            Me.LV_Syms.Columns(e.Column)

        ' Figure out the new sorting order.
        Dim sort_order As System.Windows.Forms.SortOrder
        If m_SortingColumn Is Nothing Then
            ' New column. Sort ascending.
            sort_order = SortOrder.Ascending
        Else
            ' See if this is the same column.
            If new_sorting_column.Equals(m_SortingColumn) Then
                ' Same column. Switch the sort order.
                If m_SortingColumn.Text.StartsWith("^") Then
                    sort_order = SortOrder.Descending
                Else
                    sort_order = SortOrder.Ascending
                End If
            Else
                ' New column. Sort ascending.
                sort_order = SortOrder.Ascending
            End If

            ' Remove the old sort indicator.
            m_SortingColumn.Text = _
                m_SortingColumn.Text.Substring(2)
        End If

        ' Display the new sort order.
        m_SortingColumn = new_sorting_column
        If sort_order = SortOrder.Ascending Then
            m_SortingColumn.Text = "^ " & m_SortingColumn.Text
        Else
            m_SortingColumn.Text = "v "  & m_SortingColumn.Text
        End If

        ' Create a comparer.
        Me.LV_Syms.ListViewItemSorter = New _
            ListViewComparer(e.Column, sort_order)

        ' Sort.
        Me.LV_Syms.Sort()


    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '

    Private Sub CD_Ins_FormClosing( _
        ByVal sender As Object, _
        ByVal e As System.Windows.Forms.FormClosingEventArgs) _
        Handles Me.FormClosing

        Call CMain.GetTxDbl(Me.TX_Scale,CM_Symbols.Stgs.dScl)
        Call CMain.GetTxDbl(Me.TX_Rot,CM_Symbols.Stgs.dRot)
        Call CMain.GetTxDbl(Me.TX_Span,CM_Symbols.Stgs.dSpan)

    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub CD_Ins_Load( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles MyBase.Load

        colCrt = Drawing.Color.Red
        colDbf = Drawing.Color.Blue
        colOther = Drawing.Color.Black


        Me.Text = CMain._T(TX.SYMBOLS) & ". " & _
                CMain._T(TX.INSERT) & "."
        Me.B_Close.Text = CMain._T(TX.CLOSE)

        Me.LB_SymList.Text = CMain._T(TX.SYMLIST)
        Me.CH_Name.Text = CMain._T(TX.NAME)
        Me.CH_Source.Text = CMain._T(TX.SOURCE)

        Me.GRP_Prop.Text = CMain._T(TX.PROPERT)
        Me.LB_Span.Text = CMain._T(TX.SPAN)
        Me.LB_Scale.Text = CMain._T(TX.SCALE)
        Me.LB_Rot.Text = CMain._T(TX.ROT)
        Me.B_Span.Text = CMain._T(TX.PICK)
        Me.B_Scale.Text = CMain._T(TX.PICK)
        Me.B_Rot.Text = CMain._T(TX.PICK)

        Me.GRP_Commands.Text = CMain._T(TX.CMDS)
        Me.B_ImpDef.Text = CMain._T(TX.SY_IMPDEF)
        Me.B_PlaceOne.Text = CMain._T(TX.PLACE1)
        Me.B_OnPoly.Text = CMain._T(TX.ONPOLY)
        Me.B_OnDir.Text = CMain._T(TX.ONDIR)
        Me.B_Refresh.Text = CMain._T(TX.REFRESH)

        Me.lbl_CrtDrawing.Text = CMain._T(TX.CURRENT)
        Me.lbl_DBF.Text = CMain._T(TX.TEMPLATE)
        Me.lbl_Others.Text = CMain._T(TX.OTHERS)

        ScanForBlocks()

        Me.TX_Scale.Text = CM_Symbols.Stgs.dScl.ToString()
        Me.TX_Rot.Text = CM_Symbols.Stgs.dRot.ToString()
        Me.TX_Span.Text = CM_Symbols.Stgs.dSpan.ToString()

        Me.col_CrtDrawing.BackColor = colCrt
        Me.col_DBF.BackColor = colDbf
        Me.col_Others.BackColor = colOther

    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub LV_Syms_SelectedIndexChanged( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles LV_Syms.SelectedIndexChanged

        Try
            If Me.LV_Syms.SelectedItems.Count <> 1 Then Exit Try
            '// the code below does not work
            '// the error is with  btr.PreviewIcon; there seems to be no icon
            Exit Try
            'Dim sBlkName As String = _
            '    Me.LV_Syms.SelectedItems(0).Text

            'If Me.LV_Syms.SelectedItems(0).SubItems(1).Text = CMain._T(TX.DBF) Then
            '    '// this block is located in database

            '    '// search external database
            '    Dim acSrcDb As Database = _
            '        New Database(False, True)
            '    Try
            '        ' Read the DWG into a side database
            '        acSrcDb.ReadDwgFile(CM_Symbols.Stgs.sDBPath, _
            '                            System.IO.FileShare.Read, True, "")

            '        Using myT As Transaction = acSrcDb. _ 
            '            TransactionManager.StartTransaction()

            '            ' Open the block table
            '            Dim bt As BlockTable = DirectCast( _
            '                myT.GetObject(acSrcDb.BlockTableId, _
            '                             OpenMode.ForRead, False),  _
            '                            BlockTable)
            '            Dim btr As BlockTableRecord
            '            If (bt.Has(sBlkName)) Then
            '                '// found the block
            '                btr = DirectCast( _
            '                myT.GetObject(bt(sBlkName), _
            '                             OpenMode.ForRead, False),  _
            '                            BlockTableRecord)
            '                '// aaand now we have the block
            '                If btr.HasPreviewIcon Then
            '                    Me.PCB_Preview.BackgroundImage = _
            '                    btr.PreviewIcon
            '                End If
            '                btr.Dispose()
            '            Else
            '                '// database no longer has this block
            '            End If

            '        End Using
            '    Catch ex As System.Exception
            '        CMain.DebugException(ex)
            '    Finally
            '        If Not acSrcDb Is Nothing Then
            '            acSrcDb.Dispose()
            '            acSrcDb = Nothing
            '        End If
            '    End Try
            'Else
            '    '// is located in one of the drawings (may not be current one)
            '    For Each acDoc As Document In Autodesk.AutoCAD.ApplicationServices. _
            '                Application.DocumentManager
            '        If acDoc.Name = Me.LV_Syms.SelectedItems(0).SubItems(1).Text
            '            '// found it
            '            Using acDocLk As DocumentLock = acDoc.LockDocument()
            '            Using myT As Transaction = acDoc.Database. _ 
            '                TransactionManager.StartTransaction()
            '            Try
            '                '// we're ready to get that nasty block

            '                ' Open the block table
            '                Dim bt As BlockTable = DirectCast( _
            '                    myT.GetObject(acDoc.Database.BlockTableId, _
            '                                 OpenMode.ForRead, False),  _
            '                                BlockTable)
            '                Dim btr As BlockTableRecord
            '                If (bt.Has(sBlkName)) Then
            '                    '// found the block
            '                    btr = DirectCast( _
            '                    myT.GetObject(bt(sBlkName), _
            '                                 OpenMode.ForRead, False),  _
            '                                BlockTableRecord)
            '                    '// aaand now we have the block
            '                    If btr.HasPreviewIcon Then
            '                        Me.PCB_Preview.BackgroundImage = _
            '                        btr.PreviewIcon
            '                    End If
            '                    btr.Dispose()
            '                Else
            '                    '// database no longer has this block
            '                End If
            '            Catch ex As System.Exception
            '                CMain.DebugException(ex)
            '            End Try
            '            End Using
            '            End Using

            '            Exit Try
            '        End If
            '    Next
            '    '//  we could not locate the drawing that this block belongs to
            '    '// the drawing may have been closed
            'End If
        Catch ex As System.Exception
            CMain.DebugException(ex)
        Finally
        End Try
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub B_Refresh_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles B_Refresh.Click


        LV_Syms.Items.Clear()

        ScanForBlocks()
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub B_Close_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles B_Close.Click


        Me.Close()
    End Sub
    '// ===================================================================== '

#End Region


#Region "Action events"

    '// --------------------------------------------------------------------- '
    Private Sub DefImported(ByRef sNew As String)

        If Not (sNew Is Nothing) Then
            Dim li As System.Windows.Forms.ListViewItem
            li = Me.LV_Syms.Items.Add(sNew)
            li.SubItems.Add( _
                Autodesk.AutoCAD.ApplicationServices. _
                    Application.DocumentManager.MdiActiveDocument.Name)
            li.ForeColor = Drawing.Color.Red
        End If

    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub B_ImpDef_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles B_ImpDef.Click

        Me.Hide()
        Dim sNew As String = Nothing
        ActionBase(ACTY.REGISTER, sNew)
        DefImported(sNew)
        Autodesk.AutoCAD.ApplicationServices. _
            Application.ShowModelessDialog(Me)
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub B_PlaceOne_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles B_PlaceOne.Click

        Me.Hide()
        Dim sNew As String = Nothing
        ActionBase(ACTY.INS_POINT, sNew)
        DefImported(sNew)
        Autodesk.AutoCAD.ApplicationServices. _
            Application.ShowModelessDialog(Me)
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub B_OnPoly_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles B_OnPoly.Click

        Me.Hide()
        Dim sNew As String = Nothing
        ActionBase(ACTY.INS_POLY, sNew)
        DefImported(sNew)
        Autodesk.AutoCAD.ApplicationServices. _
            Application.ShowModelessDialog(Me)
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub B_OnDir_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles B_OnDir.Click

        Me.Hide()
        Dim sNew As String = Nothing
        ActionBase(ACTY.INS_DIR, sNew)
        DefImported(sNew)
        Autodesk.AutoCAD.ApplicationServices. _
            Application.ShowModelessDialog(Me)
    End Sub
    '// ===================================================================== '

#End Region

#Region "Pick"
    '// --------------------------------------------------------------------- '
    Private Sub B_Span_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles B_Span.Click

        Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices. _
            Application.DocumentManager.MdiActiveDocument
        If acDoc Is Nothing Then
            Me.Close()
            Return
        End If

        Me.Hide()

        Try

            Dim ppo As PromptPointOptions
            Dim ppr As PromptPointResult
            Dim dN1 As Double, dE1 As Double

            ppo = New PromptPointOptions(vbLf & CMain._T(TX.FPOINT) & ":")

            ppr = acDoc.Editor.GetPoint(ppo)
            If ppr.Status = PromptStatus.OK Then
                dN1 = ppr.Value.Y
                dE1 = ppr.Value.X
            Else
                Exit Try
            End If

            ppo.BasePoint = ppr.Value
            ppo.UseBasePoint = True
            ppo.Message = vbLf & CMain._T(TX.SPOINT) & ":"
            Dim dDn As Double
            Dim dDe As Double
            Do
                ppr = acDoc.Editor.GetPoint(ppo)
                If ppr.Status <> PromptStatus.OK Then Exit Try
                dDn = ppr.Value.Y - dN1
                dDe = ppr.Value.X - dE1

                If Math.Abs(dDn) > CMain.MARGIN Then
                    Exit Do
                End If
                If Math.Abs(dDe) > CMain.MARGIN Then
                    Exit Do
                End If
                CMain.AlertUser(TX.ERR_PTCLOSE)
            Loop

            Me.TX_Span.Text = ( _
                Math.Sqrt(dDn * dDn + dDe * dDe) _
            ).ToString("0.000")


        Catch ex As System.Exception
            CMain.DebugException(ex)
        End Try

        Autodesk.AutoCAD.ApplicationServices.Application. _
            ShowModelessDialog(Me)
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub B_Scale_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles B_Scale.Click


        Me.Hide()
        Dim bOk As Boolean
        Dim dRes As Double
        dRes = CMain.GetScaleFromUser(bOk)

        If bOk = True Then
            Me.TX_Scale.Text = dRes.ToString()
        End If

        Autodesk.AutoCAD.ApplicationServices.Application. _
            ShowModelessDialog(Me)
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Private Sub B_Rot_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles B_Rot.Click


        Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices. _
            Application.DocumentManager.MdiActiveDocument
        If acDoc Is Nothing Then
            Me.Close()
            Return
        End If

        Me.Hide()

        Try
            Dim dDn As Double
            Dim dDe As Double
            Dim ppo As PromptPointOptions
            Dim ppr As PromptPointResult
            Dim dN1 As Double, dE1 As Double
            Dim dAng1 As Double, dAng2 As Double


            '// get first segment
            ppo = New PromptPointOptions(vbLf & CMain._T(TX.SYM_SCL1) & ":")

            ppr = acDoc.Editor.GetPoint(ppo)
            If ppr.Status <> PromptStatus.OK Then Exit Try
            dN1 = ppr.Value.Y
            dE1 = ppr.Value.X

            ppo.BasePoint = ppr.Value
            ppo.UseBasePoint = True
            ppo.Message = vbLf & CMain._T(TX.SYM_SCL2) & ":"
            Do
                ppr = acDoc.Editor.GetPoint(ppo)
                If ppr.Status <> PromptStatus.OK Then Exit Try
                dDn = ppr.Value.Y - dN1
                dDe = ppr.Value.X - dE1

                If Math.Abs(dDn) > CMain.MARGIN Then
                    Exit Do
                End If
                If Math.Abs(dDe) > CMain.MARGIN Then
                    Exit Do
                End If
                CMain.AlertUser(TX.ERR_PTCLOSE)
            Loop
            dAng1 = Math.Atan2(dDn, dDe)

            '// get new position of reference point
            ppo.Message = vbLf & CMain._T(TX.SYM_SCL4) & ":"
            Do
                ppr = acDoc.Editor.GetPoint(ppo)
                If ppr.Status <> PromptStatus.OK Then Exit Try
                dDn = ppr.Value.Y - dN1
                dDe = ppr.Value.X - dE1

                If Math.Abs(dDn) > CMain.MARGIN Then
                    Exit Do
                End If
                If Math.Abs(dDe) > CMain.MARGIN Then
                    Exit Do
                End If
                CMain.AlertUser(TX.ERR_PTCLOSE)
            Loop
            dAng2 = Math.Atan2(dDn, dDe)


            Me.TX_Rot.Text = ( _
                dAng2 - dAng1 _
            ).ToString()


        Catch ex As System.Exception
            CMain.DebugException(ex)
        End Try

        Autodesk.AutoCAD.ApplicationServices.Application. _
            ShowModelessDialog(Me)
    End Sub
    '// ===================================================================== '
#End Region



End Class


'//  CLASS    =============================================================== '
'//
'//
'//
'//
'//  FUNCTIONS    ----------------------------------------------------------- '

'//  FUNCTIONS    =========================================================== '
'//
'//
'//
'//
'// ------------------------------------------------------------------------- '
'// ========================================================================= '
